#ifndef __HTTP_DOWNLOAD_H__
#define __HTTP_DOWNLOAD_H__

#include <curl/curl.h>

#include <cstring>
#include <string>

#include "common.h"
#include "curl_util.h"
#include "download.h"
#include "order_buffer.h"
#include "thread_pool.h"

// todo: 并没有自适应sdd类型，充分利用sdd的并行写能力
class HttpDownloader : public Downloader
{
  private:
    // 跟踪Curl的回调接受状态
    struct TrackRecevieContext
    {
        Chunk chunk;
        // 期待的期待的字节数（由调度线程计算好）
        size_t expected;
        // 已写入的字节数
        size_t written;
        // 标记块是否完整
        bool completed;

        TrackRecevieContext(const size_t rhsSeq, const size_t rhsExpected)
            : expected(rhsExpected), chunk(rhsSeq, rhsExpected)
        {
            written = 0;
            completed = false;
        }

        ~TrackRecevieContext() = default;
    };

  public:
    HttpDownloader(ThreadPool &download, ThreadPool &writeDisk)
        : downloadPool(download), writeDiskPool(writeDisk)
    {
    }

    ~HttpDownloader() = default;

  public:
    // 对外接口，负责启动接受线程、写磁盘线程
    error_t work(const std::string &url, const std::string &output) override;

  private:
    error_t getFileSize(const std::string &url, long &fileSize) override;

    // 测试发现python3 -m http.server 8080不支持range
    bool checkRangeSupport(const std::string &url) override;

    static size_t discardDataCallback(char *, size_t size, size_t nmemb, void *)
    {
        return size * nmemb;
    }

    // curl的回调
    static size_t curlWriteCallback(char *ptr, size_t size, size_t nmemb, void *userdata);

    // 支持range的下载线程的线程函数
    void downloadFunByRange(const std::string &url, const size_t chunkSeq, const size_t expected);

    // 不支持range的下载线程的线程函数
    void downloadFun(const int id, const std::string &url, const size_t expected);

    // O_DIRECT写入磁盘线程的线程函数(这里是为hdd设计的，没有考虑sdd的并行写能力，比如可以每次取10个有序递增的Chunk分配给一个线程)
    void writeToDisk(const std::string fileName, const size_t fileSize);

  private:
    // 自动合并已排序的Buffer类
    OrderBuffer orderBuffer;

    ThreadPool &downloadPool;
    ThreadPool &writeDiskPool;
};

#endif  //__HTTP_DOWNLOAD_H__